﻿using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;

using Autofac;
using Autofac.Core.Lifetime;

namespace Zeus.DependencyInjection
{
    public class AutofacWebApiDependencyResolver : IDependencyResolver
    {

        private bool _disposed;
        ILifetimeScope _container;
        IDependencyScope _rootDependencyScope;
        ContainerBuilder _containerBuilder;


        public AutofacWebApiDependencyResolver()
        {
            _containerBuilder = new ContainerBuilder();
        }

        ~AutofacWebApiDependencyResolver()
        {
            Dispose(false);
        }

        public ContainerBuilder ContainerBuilder
        {
            get {
                return _containerBuilder;
            }
        }

        public ILifetimeScope Container
        {
            get { return _container; }
        }

        public void Build()
        {
            _container = ContainerBuilder.Build();
            _rootDependencyScope = new AutofacWebApiDependencyScope(_container);
        }

        public virtual object GetService(Type serviceType)
        {
            return _rootDependencyScope.GetService(serviceType);
        }

        /// <summary>
        /// Try to get a list of services of the given type.
        /// </summary>
        /// <param name="serviceType">ControllerType of services to request.</param>
        /// <returns>An enumeration (possibly empty) of the service.</returns>
        public virtual IEnumerable<object> GetServices(Type serviceType)
        {
            return _rootDependencyScope.GetServices(serviceType);
        }

        public IDependencyScope BeginScope()
        {
            var lifetimeScope = _container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
            return new AutofacWebApiDependencyScope(lifetimeScope);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    if (_rootDependencyScope != null)
                    {
                        _rootDependencyScope.Dispose();
                    }
                }
                _disposed = true;
            }
        }
    }
}
